/**  
* @Title: Service.java
* @Package com.lemon.conf.socket
* @Description: (一句话阐述):
* @author Ran_cc
* @date 2018年7月19日
* @version V1.0  
*/
package com.lemon.conf.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * <p>Title: Service</p>
 * <p>Description: 
 * </p>
 * <p>Company: </p>
 * @author Ran_cc
 * @date 2018年7月19日
 * @版本 V 1.0 
 */
public class Server {

	/*
	 * private static TkOrderRecordService TkOrderRecordService() {
	 * ApplicationContext applicationContext = SpringContextUtil.getApplicationContext();
	 * TkOrderRecordService bean = applicationContext.getBean(TkOrderRecordService.class);
	 * return bean;
	 * }
	 */

	public static List<String> tkList = new ArrayList<String>(); //返回给客户端要处理的String list

	public static void tkListAdd(String id) {
		if (!tkList.contains(id)) {
			tkList.add(id);
		}
	}
	/**
	 * 要处理客户端发来的对象，并返回一个对象，可实现该接口。
	 */
	public interface ObjectAction {
		Object doAction(Object rev);
	}

	/**
	 * <p>
	 * Title: DefaultObjectAction
	 * </p>
	 * <p>
	 * Description: 接受客户端的消息并返回信息
	 * </p>
	 * <p>
	 * Company:
	 * </p>
	 * 
	 * @author Ran_cc
	 * @date 2018年7月20日
	 * @版本 V 1.0
	 */
	public static final class DefaultObjectAction implements ObjectAction {
		public Object doAction(Object rev) {
			//			System.out.println("接受客户端发来的消息-：" + rev);
			if (rev != null) {
				JSONObject parse = (JSONObject) JSONObject.parse(rev.toString());
				String str = parse.getString("type");
				if ("1".equals(str)) {
					System.out.println(parse.toJSONString());
					new Thread(new Runnable() {
						@Override
						public void run() {
							//							TkOrderRecordService().insertTkOrderByFiveMon(parse);
						}
					}).start();
				} else if ("2".equals(str)) {
					//封装返回的数据集
					if (tkList.size() > 0) {
						Object obj = tkList;
						tkList = new ArrayList<String>();
						String string = JSON.toJSONString(obj);
						String j = "{\"type\":\"2\",\"obj\":" + string + "}";
						return j;
					}
				} else {
					System.out.println("其他类型");
					System.out.println(parse.toJSONString());
				}
			}
			return "{\"type\":\"0\",\"obj\":\"f\"}";
		}
	}
	public static void main(String[] args) {
		int port = 65432;
		Server server = new Server(port);
		server.start();
	}
	public Server() {
		int port = 65432;
		Server server = new Server(port);
		server.start();
	}
	private int port;
	private volatile boolean running = false;
	//	private long receiveTimeDelay = 1000 * 60 * 10; //10分钟
	private long receiveTimeDelay = 1000 * 60; //60秒
	private ConcurrentHashMap<Class , ObjectAction> actionMapping = new ConcurrentHashMap<Class , ObjectAction>();
	private Thread connWatchDog;

	public Server(int port) {  
        this.port = port;  
    }

	public void start() {
		if (running) {
			return;
		}
		running = true;
		connWatchDog = new Thread(new ConnWatchDog());
		connWatchDog.start();
		System.out.println("--socket start----");
	}

	@SuppressWarnings("deprecation")
	public void stop() {
		if (running)
			running = false;
		if (connWatchDog != null)
			connWatchDog.stop();
	}

	public void addActionMap(Class<Object> cls , ObjectAction action) {
		actionMapping.put(cls , action);
	}

	class ConnWatchDog implements Runnable {
		public void run() {
			try {
				System.out.println("WatchDog socket");
				ServerSocket ss = new ServerSocket(port, 5);
				while (running) {
					Socket s = ss.accept();
					new Thread(new SocketAction(s)).start();
				}
			} catch (IOException e) {
				e.printStackTrace();
				Server.this.stop();
			}

		}
	}

	class SocketAction implements Runnable {
		Socket s;
		boolean run = true;
		long lastReceiveTime = System.currentTimeMillis();

		public SocketAction(Socket s) {
			System.out.println("scoketAction :" + s);
			this.s = s;
		}

		ObjectInputStream ois = null;
		Object obj = null;
		public void run() {
			while (running && run) {
				if (System.currentTimeMillis() - lastReceiveTime > receiveTimeDelay) {
					overThis();
				} else {
					try {
						InputStream in = s.getInputStream();
						if (in.available() > 0) {
								ois = new ObjectInputStream(in);
								obj = ois.readObject();
							lastReceiveTime = System.currentTimeMillis();
							//							System.out.println("接收：\t" + obj);
							ObjectAction oa = actionMapping.get(obj.getClass());
							oa = oa == null ? new DefaultObjectAction() : oa;
							Object out = oa.doAction(obj);
							if (out != null) {
								ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
								oos.writeObject(out);
								oos.flush();
							}
						} else {
							Thread.sleep(10);
						}
					} catch (Exception e) {
						e.printStackTrace();
						overThis();
					}
				}
			}
		}

		private void overThis() {
			if (run)
				run = false;
			if (s != null) {
				try {
					s.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			System.out.println("关闭：" + s.getRemoteSocketAddress());
		}

	}
}
